/* Copyright (C) 2010 Fredrique Samuels, fredriquesamuels@gmail.com 

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iostream>

#include "threads.h"
#include <pthread.h>


void* __run_thread_via_pthreads__(void* t){
    ((tri::thread*)t)->_run();
    return NULL;
}

namespace tri{

thread_mutex::thread_mutex(){}
thread_mutex::~thread_mutex(){unlock();}

void thread_mutex::lock(){
    pthread_mutex_lock (&mutex);
}

void thread_mutex::unlock(){
    pthread_mutex_unlock (&mutex);
}

thread::thread():is_running(false),_terminate(false){}
thread::~thread(){}

int thread::start(){
    if (!isRunning()){
        return pthread_create(&_thread_, NULL, __run_thread_via_pthreads__ ,this);
    }
    return -1;
        
}


void thread::_run(){
    setRunning(true);
    _terminate =false;
    try{
        run();
    }catch(...){
        setRunning(false);
        std::cerr<<"TRI::WARNING Unhandled Exception in thread"<<std::endl;
    }
    setRunning(false);
    _terminate =false;
    pthread_exit((void*) 0);
}

bool thread::isRunning(){
    return is_running;
}

void thread::terminate(){
    if(isRunning()){
        _terminate = true;
    }
}

void thread::wait_on_exit(){
    while(isRunning() && request_terminate()){
        Sleep(100);
    }
}

bool thread::request_terminate(){
    return _terminate;
}


void thread::setRunning(bool b){
    is_running = b;
}

timer::timer(timeout* t,double sec):thread(),to(t){
    setTime(sec);
    _timer.setMode(TIMER_MODE);
}


timer::~timer(){}

void timer::setTime(double sec){
    _timer.setDurationTime(sec);
}

void timer::run(){
    _timer.start();
    while(1){
        _timer.getElapsedTime();
        utils::sleep(10);
        if(!_timer.isRunning()){
            if(to!=NULL){
                to->on_timeout();
            }
			TIMEOUT.emit();
            _timer.reset();
        }
        if(request_terminate()){
            break;
        }
    }
    _timer.stop();
}

void timer::reset(){
    terminate();
    wait_on_exit();
    start();
}

void timer::stop(){
    terminate();
}

timeout::timeout(){}
timeout::~timeout(){}


}

